<template>
  <div class="tree-graph-container">
    <treeToolbar @enlarge="onEnlarge" @narrow="onNarrow" />
    <div id="x6Container" class="x6Container" ref="containerRef"></div>
    <TeleportContainer />
    <!-- 详情 -->
    <depInfoDetailDrawer ref="depInfoDetailDrawerRef"></depInfoDetailDrawer>
  </div>
</template>

<script setup lang="ts">
import { h as h2, onMounted, ref, shallowRef, defineExpose } from "vue";
import treeNodeCard from "@/views/x6-deptTree/components/treeNodeCard.vue";
import treeLineCard from "@/views/x6-deptTree/components/treeLineCard.vue";
import treeCollapsAbleNode from "@/views/x6-deptTree/components/treeCollapsAbleNode.vue";
import connectEmptyBoxesCard from "@/views/x6-deptTree/components/connectEmptyBoxesCard.vue";
import treeNodeNumberCard from "@/views/x6-deptTree/components/treeNodeNumberCard.vue";
import treeNodeCustomCard from "@/views/x6-deptTree/components/treeNodeCustomCard.vue";
import treeNodeSmallCustomCard from "@/views/x6-deptTree/components/treeNodeSmallCustomCard.vue";
import treeToolbar from "@/views/x6-deptTree/components/treeToolbar.vue";
import depInfoDetailDrawer from "./preparationDetail.vue";

import { Graph } from "@antv/x6";
import { dataToTreeData } from "@/utils/cs.ts";
import { register, getTeleport } from "@antv/x6-vue-shape";
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
import { Export } from "@antv/x6-plugin-export";
import { newData } from "./data.ts";
import { base64ToImg, imgToCanvas, addWatermark, downloadFile, ranDomFileName } from "@/utils/index";
import { ElLoading } from "element-plus";

interface TreeSize {
  width: number;
  height: number;
}

// teleport ref
const TeleportContainer = getTeleport();

// 树状图的尺寸
const treeSize = ref<TreeSize>({ width: 0, height: 0 });

// x6 图的实例
const graphInstance = shallowRef();

// 节点原始数据
const orignalData = ref<[]>([]);

let graph: Graph | null = null;

const depInfoDetailDrawerRef = ref();

// 初始化树
const initData = () => {
  // 初始化 x6 图背景板
  // 创建一个新的 Graph 实例
  graph = new Graph({
    // 指定 Graph 的容器元素
    container: document.getElementById("x6Container")!,

    // 自动调整 Graph 的大小以适应容器
    autoResize: true,

    // 设置背景颜色
    background: {
      color: "#fff" // 背景颜色设置为浅灰色
    },

    // 滚动设置
    scroller: {
      enabled: false, // 启用滚动
      pannable: true // 允许通过拖动来平移视图
    },

    // 是否启用缩略图（小地图）
    minimap: false, // 禁用缩略图

    // 鼠标滚轮设置
    mousewheel: {
      enabled: false // 启用鼠标滚轮缩放
      // modifiers: ['ctrl', 'meta'] // 可以通过按下 Ctrl 或 Meta 键来启用缩放（此行被注释掉）
    },

    // 平移设置
    panning: {
      enabled: true // 启用平移功能
      // modifiers: 'space' // 需要按住 space 键才能进行拖拽平移 大空格键
    },

    // 交互设置
    interacting: {
      nodeMovable: false // 禁止节点移动
    }

    // 拖拽设置（此部分被注释掉）
    // dragging: {
    //   enabled: true, // 启用拖拽功能
    //   ghost: false   // 禁用拖拽时的虚影效果
    // }
  });

  orignalData.value = newData as never;

  const randomData = dataToTreeData(
    { data: orignalData.value }
    // pId 父id   id自身
  ); // 转化成x6节点数据
  // console.log(randomData, "数据格式化化之后");

  treeSize.value = randomData.size; // 树的大小

  // 渲染
  graph.fromJSON({
    nodes: randomData.nodes as never,
    edges: randomData.edges as never
  });

  graph.zoomToFit(); // 缩放
  graph.scale(0.7); // 设置初始缩放比例，例如 0.7 表示缩小到 70%
  graph.centerContent(); // 居中
  graph.use(new Export()); // 加载导出插件
  graphInstance.value = graph; // 保存图实例
};

// 详情
const handleDetail = data => {
  depInfoDetailDrawerRef.value.openDialog(data.state);
};

const initTreeNode = () => {
  // 使用封装的函数注册不同的节点
  register({
    shape: "treeNodeCard",
    width: 100,
    height: 100,
    component: {
      render: () =>
        h2(treeNodeCard, {
          // 点击卡片打开详情卡片
          onHandleClick: data => {
            handleDetail(data);
          },
          // 添加子节点
          onHandleAddIcon: data => {
            console.log(data);
          },
          // 删除子节点
          onHandleRemoveIcon: data => {
            console.log(data);
          }
        })
    }
  });
  register({
    shape: "treeLineCard",
    width: 50,
    height: 50,
    component: treeLineCard
  });
  register({
    shape: "treeCollapsAbleNode",
    width: 50,
    height: 50,
    zIndex: 99,
    component: {
      render: () =>
        h2(treeCollapsAbleNode, {
          data: orignalData.value,
          // 展开收缩节点
          onHandleExpandCollapse: data => {}
        })
    }
  });
  register({
    shape: "connectEmptyBoxesCard",
    width: 50,
    height: 50,
    zIndex: 99,
    component: {
      render: () => h2(connectEmptyBoxesCard, {})
    }
  });
  register({
    shape: "treeNodeNumberCard",
    width: 50,
    height: 50,
    zIndex: 99,
    component: treeNodeNumberCard
  });
  register({
    shape: "treeNodeCustomCard",
    width: 500,
    height: 800,
    component: treeNodeCustomCard
  });
  register({
    shape: "treeNodeSmallCustomCard",
    width: 500,
    height: 800,
    zIndex: 99,
    component: treeNodeSmallCustomCard
  });
};
/* ******************导出开始**************************************** */
const handleExport = async ({ type, value, width, height }) => {
  const loading = ElLoading.service({
    lock: true,
    text: "加载中...",
    background: "rgba(255, 255, 255, 0)"
  });
  const bbox = graph!.getContentBBox();

  const params = {
    width: value === "big" ? (type === "PNG" ? Number(bbox.width) * 2 : 7680) : width,
    height: value === "big" ? (type === "PNG" ? Number(bbox.height) * 2 : 4320) : height
  };

  const base64URI = await exportBase64(params);

  console.log("base64URI", base64URI);

  const img = await base64ToImg(base64URI);
  const ctx = imgToCanvas(img);
  // 添加水印
  addWatermark(ctx, "waiting");
  // 使用 toDataURL 方法将 canvas 内容转换为图片数据 URL
  const dataURL = ctx.toDataURL("image/png");
  if (dataURL !== "") {
    if (type === "PNG") {
      // 下载图片
      downloadFile(ranDomFileName("组织架构图"), dataURL);
    } else if (type === "PDF") {
      const canvas = await html2canvas(graph!.container, { scale: 2 });
      // 使用jspdf创建PDF文档
      // eslint-disable-next-line new-cap
      const pdf = new jsPDF({
        orientation: "landscape",
        unit: "px",
        format: [canvas.width, canvas.height]
      });
      pdf.addImage(dataURL, "PNG", 0, 0, canvas.width, canvas.height);
      // 保存PDF
      pdf.save(`${ranDomFileName("组织架构图")}.pdf`);
    }
    loading.close();
  }
};

const exportBase64 = async ({ width, height }): Promise<string> => {
  return new Promise(resolve => {
    // Wait for a small delay to ensure styles are applied
    setTimeout(() => {
      graph!.toPNG(
        async dataURL => {
          await new Promise(resolve => setTimeout(resolve, 0));
          resolve(dataURL);
        },
        {
          padding: 300,
          quality: 1,
          width,
          height,
          copyStyles: true, // Ensure styles are copied
          backgroundColor: "#fff"
        }
      );
    }, 100); // Adjust the timeout if needed
  });
};

/* ******************导出结束**************************************** */

/* ******************放大/缩小/全屏开始**************************************** */

const onEnlarge = () => {
  graphInstance.value.zoom(0.1);
};

const onNarrow = () => {
  graphInstance.value.zoom(-0.1);
};
/* ******************放大/缩小/全屏结束**************************************** */

onMounted(() => {
  initTreeNode(); // 注册节点
  initData(); // 初始化树数据
});

defineExpose({ handleExport });
</script>

<style lang="scss" scoped>
.tree-graph-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background-color: rgb(239, 240, 245);
}

.x6Container {
  flex: 1;
  width: 100%;
  height: calc(100% - 100px);
  position: relative;
}
</style>
